/*
 * =====================================================================================
 *
 *       Filename:  compiler.h
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  02/28/12 14:22:13
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  randyli (randy), randyli@tencent.com
 *        Company:  Tencent
 *
 * =====================================================================================
 */


#ifndef  COMPILER_INC
#define  COMPILER_INC

#include "vm.h"
#include "array.h"
#include <stdio.h>
//the lexer
#define YYSETCONDITION(s) (l->yystate) = s
#define YYGETCONDITION()  (l->yystate)
#define STATE(name)  yyc##name
#define BEGIN(state) YYSETCONDITION(STATE(state))
#define YYSTATE      YYGETCONDITION()
#define YYCURSOR  yycursor
#define YYMARKER  yymarker


/* conditions */
enum YYCONDTYPE {
	yycINITIAL,
	yycSMARTY
};

typedef struct _token
{
	int type;
	object val;
}token;

typedef struct _lexer
{
	char* buf; /* the lexer text buffer */
	int   len;
	char* cursor; /* the lexer cursor */
	int   yystate; /* the lexer's current state*/
}lexer;

int get_next_token(lexer* l, token* yyvalue);

struct _scompiler;
//parser
void *ParseAlloc(void *(*mallocProc)(size_t));
void ParseFree( void *p,void (*freeProc)(void*));
void Parse( void *yyp,int yymajor,token yyminor, struct _scompiler* compiler );

//the compiler
typedef struct _tag
{
	char type[16];
	int arg1;
	int arg2;
}tag;

//the symbol table
typedef struct _symbol
{
	char name[256];
	int  offset; //the offset in stack
}symbol;

int add_symbol(smt_array* st, const char* name, int name_offset);
int get_symbol(smt_array* st, const char* name);


typedef struct _scompiler
{

	lexer* lex;
	void * parser;	
#ifdef __DEBUG
	FILE* dfp;//parser debug information
#endif
	smt_array* st;
	
	tag open_tags[1024];
	int open_tag_num;		
	
	opcode ops[1024]; //the opcodes buffer;
	int ops_num;
	
	opcode tmp_ops[1024]; //the tmp opcodes buffer used for undesided opcodes ;
	int tmp_ops_num;
	
	char sconst[102400];	
	int  sconst_pos; 
	
	int  rand_index; //a rand variable generator;
	
}scompiler;

int compiler_init(scompiler** p_compiler);
int compile_str(scompiler* compiler, char* str, int len);
int compiler_destroy(scompiler* compiler);

// add a new opcode with a int(float , string) argument
int add_iopcode(scompiler* compiler, int opcode, int   arg1);
int set_iopcode(scompiler* compiler, int pos, int opcode, int   arg1);
int add_fopcode(scompiler* compiler, int opcode, float arg1);
int add_sopcode(scompiler* compiler, int opcode, char* arg1);

int add_tmp_iopcode(scompiler* compiler, int opcode, int  arg1);
int merge_opcode(scompiler* compiler);

// open tag stack opration
int open_tag(scompiler* compiler, const char* type, int arg1, int arg2);
tag* top_tag(scompiler* compiler);
int close_tag(scompiler* compiler, const char* type);

// variable 
int tmp_variable(scompiler* compiler, const char* name);

//rand variable
int rand_variable(scompiler* compiler, const char* prefix, char* out);

int exe_out(scompiler* compiler, const char* file);

#endif   /* ----- #ifndef COMPILER_INC  ----- */
